#include "disk_manager.h"
#include "utils/logger.h"
#include <filesystem>
#include <stdexcept>
#include <cstring>

// 构造函数
DiskManager::DiskManager(const std::string& db_file_path, const std::string& meta_file_path)
    : db_file_path_(db_file_path),
      meta_file_path_(meta_file_path),
      next_page_id_(1),
      page_count_(0),
      file_size_(0),
      free_list_head_(INVALID_PAGE_ID) {  // ✅ 新增：初始化空闲链表头 为无效值
    
    // 创建文件所在目录（如果不存在）
    std::filesystem::create_directories(std::filesystem::path(db_file_path).parent_path());
    
    if (!initialize_files()) {
        throw std::runtime_error("Failed to initialize database files");
    }
    
    LOG_INFO("DiskManager initialized for database: " + db_file_path);
}

// 析构函数
DiskManager::~DiskManager() {
    if (db_file_.is_open()) {
        db_file_.close();
    }
    // if (meta_file_.is_open()) {
    //     meta_file_.close();
    // }
    LOG_INFO("DiskManager destroyed for database: " + db_file_path_);
}

// 分配新页
page_id_t DiskManager::allocate_page() {
    std::lock_guard<std::mutex> lock(mutex_);
    
    try {
        // ✅ 1. 优先从空闲链表分配（LIFO：后释放的先复用）
        if (free_list_head_ != INVALID_PAGE_ID) {
            page_id_t reused_page_id = free_list_head_;

            // 读取该页前4字节，获取“下一个”空闲页
            char buffer[PAGE_SIZE];
            if (!read_page_no_lock(reused_page_id, buffer)) {
                LOG_ERROR("Failed to read freed page: " + std::to_string(reused_page_id));
                return INVALID_PAGE_ID;
            }

            // 更新空闲链表头为“下一个”
            free_list_head_ = *reinterpret_cast<page_id_t*>(buffer);

            // ✅ 无需写回该页内容（它已经是空闲页格式）
            // ✅ 无需扩展文件，页已存在

            // 更新元数据（page_count_ 不变！）
            if (!save_metadata()) {
                LOG_ERROR("Failed to save metadata after reusing page");
                // 可选择：是否回滚 free_list_head_？这里先返回失败
                return INVALID_PAGE_ID;
            }

            LOG_DEBUG("Reused freed page: " + std::to_string(reused_page_id));
            return reused_page_id;
        }

        // ✅ 2. 没有空闲页，分配新页
        page_id_t new_page_id = next_page_id_++;
        
        size_t required_size = (new_page_id) * PAGE_SIZE;
        if (required_size > file_size_) {
            if (!extend_file(required_size)) {
                LOG_ERROR("Failed to extend file for new page: " + std::to_string(new_page_id));
                return INVALID_PAGE_ID;
            }
            file_size_ = required_size;
        }

        // 初始化新页为全0
        char empty_page[PAGE_SIZE] = {0};
        if (!write_page_no_lock(new_page_id, empty_page)) {
            LOG_ERROR("Failed to initialize new page: " + std::to_string(new_page_id));
            return INVALID_PAGE_ID;
        }

        // ✅ page_count_ 和 next_page_id_ 都已更新
        page_count_++;

        if (!save_metadata()) {
            LOG_ERROR("Failed to save metadata after page allocation");
            return INVALID_PAGE_ID;
        }

        LOG_DEBUG("Allocated new page: " + std::to_string(new_page_id));
        return new_page_id;

    } catch (const std::exception& e) {
        LOG_ERROR("Exception during page allocation: " + std::string(e.what()));
        return INVALID_PAGE_ID;
    }
    
}

// 释放页
bool DiskManager::free_page(page_id_t page_id) {
    std::lock_guard<std::mutex> lock(mutex_);

    if (!validate_page_id(page_id)) {
        LOG_ERROR("Attempt to free invalid page ID: " + std::to_string(page_id));
        return false;
    }

    if (page_id == 0) {
        LOG_WARNING("Page 0 is reserved and cannot be freed.");
        return false; // 通常 page 0 是元数据页，不能释放
    }

    char buffer[PAGE_SIZE];

    // 1. 读取该页内容（我们将用前 sizeof(page_id_t) 字节存“下一个空闲页”）
    if (!read_page_no_lock(page_id, buffer)) {
        LOG_ERROR("Failed to read page during free: " + std::to_string(page_id));
        return false;
    }

    // 2. 将当前空闲链表头作为“下一个”
    *reinterpret_cast<page_id_t*>(buffer) = free_list_head_;

    // 3. 写回磁盘：这个页现在成了新的空闲链表头
    if (!write_page_no_lock(page_id, buffer)) {
        LOG_ERROR("Failed to write page during free: " + std::to_string(page_id));
        return false;
    }

    // 4. 更新空闲链表头为当前页
    free_list_head_ = page_id;

    // 5. 标记元数据已修改（用于持久化）
    if (!save_metadata()) {
        LOG_ERROR("Failed to save metadata after freeing page " + std::to_string(page_id));
        // 可选择：是否回滚？这里我们继续返回 false
        return false;
    }

    LOG_DEBUG("Freed page " + std::to_string(page_id) + ", now head of free list.");
    return true;
}

// 读取页
bool DiskManager::read_page(page_id_t page_id, char* data) {
    std::lock_guard<std::mutex> lock(mutex_);
    
    if (!validate_page_id(page_id)) {
        LOG_ERROR("Attempt to read invalid page ID: " + std::to_string(page_id));
        return false;
    }
    
    if (data == nullptr) {
        LOG_ERROR("Null data buffer provided for page read");
        return false;
    }
    
    try {
        // 计算文件偏移量
        std::streampos offset = page_id * PAGE_SIZE;
        
        // 定位文件指针
        db_file_.seekg(offset);
        if (!db_file_) {
            LOG_ERROR("Seek failed for page: " + std::to_string(page_id));
            return false;
        }
        
        // 读取页数据
        db_file_.read(data, PAGE_SIZE);
        if (db_file_.gcount() != PAGE_SIZE) {
            LOG_ERROR("Incomplete read for page: " + std::to_string(page_id) +
                     ", expected: " + std::to_string(PAGE_SIZE) +
                     ", actual: " + std::to_string(db_file_.gcount()));
            return false;
        }
        
        return true;
        
    } catch (const std::exception& e) {
        LOG_ERROR("Exception during page read: " + std::string(e.what()));
        return false;
    }
}
// 读取页，无锁版本
bool DiskManager::read_page_no_lock(page_id_t page_id, char* data) {
    
    if (!validate_page_id(page_id)) {
        LOG_ERROR("Attempt to read invalid page ID: " + std::to_string(page_id));
        return false;
    }
    
    if (data == nullptr) {
        LOG_ERROR("Null data buffer provided for page read");
        return false;
    }
    
    try {
        // 计算文件偏移量
        std::streampos offset = page_id * PAGE_SIZE;
        
        // 定位文件指针
        db_file_.seekg(offset);
        if (!db_file_) {
            LOG_ERROR("Seek failed for page: " + std::to_string(page_id));
            return false;
        }
        
        // 读取页数据
        db_file_.read(data, PAGE_SIZE);
        if (db_file_.gcount() != PAGE_SIZE) {
            LOG_ERROR("Incomplete read for page: " + std::to_string(page_id) +
                     ", expected: " + std::to_string(PAGE_SIZE) +
                     ", actual: " + std::to_string(db_file_.gcount()));
            return false;
        }
        
        return true;
        
    } catch (const std::exception& e) {
        LOG_ERROR("Exception during page read: " + std::string(e.what()));
        return false;
    }
}


// 写入页，公共接口，带有互斥锁
bool DiskManager::write_page(page_id_t page_id, const char* data) {
    std::lock_guard<std::mutex> lock(mutex_);
    std::cout<<"write_page: "<<page_id<<std::endl;  
    //检查是否合法
    if (!validate_page_id(page_id)) {
        LOG_ERROR("Attempt to write invalid page ID: " + std::to_string(page_id));
        return false;
    }
    
    if (data == nullptr) {
        LOG_ERROR("Null data provided for page write");
        return false;
    }
    
    try {
        // 计算文件偏移量
        std::streampos offset = page_id * PAGE_SIZE;
        
        // 定位文件指针
        db_file_.seekp(offset);
        if (!db_file_) {
            LOG_ERROR("Seek failed for page: " + std::to_string(page_id));
            return false;
        }
        
        // 写入页数据
        db_file_.write(data, PAGE_SIZE);
        if (!db_file_) {
            LOG_ERROR("Write failed for page: " + std::to_string(page_id));
            return false;
        }
        
        // 确保数据持久化
        db_file_.flush();
        
        return true;
        
    } catch (const std::exception& e) {
        LOG_ERROR("Exception during page write: " + std::string(e.what()));
        return false;
    }
}

// 写入页，私有接口，无互斥锁
bool DiskManager::write_page_no_lock(page_id_t page_id, const char* data) {
    std::cout<<"write_page: "<<page_id<<std::endl;  
    //检查是否合法
    if (!validate_page_id(page_id)) {
        LOG_ERROR("Attempt to write invalid page ID: " + std::to_string(page_id));
        return false;
    }
    
    if (data == nullptr) {
        LOG_ERROR("Null data provided for page write");
        return false;
    }
    
    try {
        // 计算文件偏移量
        std::streampos offset = page_id * PAGE_SIZE;
        
        // 定位文件指针
        db_file_.seekp(offset);
        if (!db_file_) {
            LOG_ERROR("Seek failed for page: " + std::to_string(page_id));
            return false;
        }
        
        // 写入页数据
        db_file_.write(data, PAGE_SIZE);
        if (!db_file_) {
            LOG_ERROR("Write failed for page: " + std::to_string(page_id));
            return false;
        }
        
        // 确保数据持久化
        db_file_.flush();
        
        return true;
        
    } catch (const std::exception& e) {
        // LOG_ERROR("Exception during page write: " + std::string(e.what()));
        return false;
    }
}

// 获取页数量
size_t DiskManager::get_page_count() const {
    std::lock_guard<std::mutex> lock(mutex_);
    return page_count_;
}

// 获取文件大小
size_t DiskManager::get_file_size() const {
    std::lock_guard<std::mutex> lock(mutex_);
    return file_size_;
}

// 强制刷盘  待定？？？？？？？？？？？？？
bool DiskManager::flush() {
    std::lock_guard<std::mutex> lock(mutex_);
    
    try {
        if (db_file_.is_open()) {
            db_file_.flush();
            return true;
        }
        return false;
    } catch (const std::exception& e) {
        LOG_ERROR("Exception during flush: " + std::string(e.what()));
        return false;
    }
}

// 检查页ID有效性
bool DiskManager::is_valid_page_id(page_id_t page_id) const {
    std::lock_guard<std::mutex> lock(mutex_);
    return validate_page_id(page_id);
}

// 私有方法实现

// 初始化文件
bool DiskManager::initialize_files() {
    try {
        // 打开或创建数据文件
        db_file_.open(db_file_path_, std::ios::in | std::ios::out | std::ios::binary);
        if (!db_file_.is_open()) {
            // 文件不存在，创建新文件
            db_file_.open(db_file_path_, std::ios::out | std::ios::binary);
            db_file_.close();
            db_file_.open(db_file_path_, std::ios::in | std::ios::out | std::ios::binary);
        }
        
        if (!db_file_.is_open()) {
            LOG_ERROR("Failed to open database file: " + db_file_path_);
            return false;
        }
        
        // 获取文件大小
        db_file_.seekg(0, std::ios::end);  //移动到文件末尾
        file_size_ = db_file_.tellg();     //获取当前位置即文件大小
        db_file_.seekg(0, std::ios::beg);  //移动回文件开头
        
        // 计算页数量
        page_count_ = file_size_ / PAGE_SIZE;
        // //next_page_id_ = page_count_;
        LOG_INFO("初始化文件数据 file size: " + std::to_string(file_size_) +
                 ", page count: " + std::to_string(page_count_));
        
        // 加载或初始化元数据
        if (!load_metadata()) {
            LOG_WARNING("Failed to load metadata, initializing new metadata");
            if (!save_metadata()) {
                LOG_ERROR("Failed to initialize metadata");
                return false;
            }
        }
        
        return true;
        
    } catch (const std::exception& e) {
        LOG_ERROR("Exception during file initialization: " + std::string(e.what()));
        return false;
    }
}

// 加载元数据
bool DiskManager::load_metadata() {
    // 简单实现：从元数据文件加载基本信息
    // 实际实现可能需要更复杂的格式
    try {
        // 1. 关键修改：用局部 std::fstream 对象替代成员变量 meta_file_
        // 每次调用都新建对象，无旧状态污染，析构时自动释放资源（避免内存泄漏）
        std::fstream meta_file_;
        meta_file_.open(meta_file_path_, std::ios::in | std::ios::binary);
        if (!meta_file_.is_open()) {
            return false; // 元数据文件不存在是正常的
        }
        
        // 读取元数据   读取并赋值
        meta_file_.read(reinterpret_cast<char*>(&next_page_id_), sizeof(next_page_id_));
        meta_file_.read(reinterpret_cast<char*>(&page_count_), sizeof(page_count_));
        meta_file_.read(reinterpret_cast<char*>(&free_list_head_), sizeof(free_list_head_)); // ✅ 读取！
        LOG_INFO("Loaded metadata: next_page_id=" + std::to_string(next_page_id_) +
                 ", page_count=" + std::to_string(page_count_) + ", free_list_head=" 
                 + std::to_string(free_list_head_));
        
        meta_file_.close();
        return true;
        
    } catch (const std::exception& e) {
        LOG_ERROR("Exception during metadata load: " + std::string(e.what()));
        return false;
    }
}

// 保存元数据
bool DiskManager::save_metadata() {
    try {

        // 1. 关键修改：用局部 std::fstream 对象替代成员变量 meta_file_
        // 每次调用都新建对象，无旧状态污染，析构时自动释放资源（避免内存泄漏）
        std::fstream meta_file_;

        meta_file_.open(meta_file_path_, std::ios::out | std::ios::binary | std::ios::trunc);
        if (!meta_file_.is_open()) {
            LOG_ERROR("Failed to open metadata file: " + meta_file_path_);
            return false;
        }
        
        // 保存元数据
        // meta_file_.write(reinterpret_cast<const char*>(&next_page_id_), sizeof(next_page_id_));
        // meta_file_.write(reinterpret_cast<const char*>(&page_count_), sizeof(page_count_));
        // meta_file_.write(reinterpret_cast<const char*>(&free_list_head_), sizeof(free_list_head_)); // ✅ 新增！
        // 写入元数据（每个字段单独检查写入结果）
        meta_file_.write(reinterpret_cast<const char*>(&next_page_id_), sizeof(next_page_id_));
        if (meta_file_.fail()) {
            LOG_ERROR("Failed to write next_page_id to metadata");
            meta_file_.close();  // 确保关闭文件
            return false;
        }

        meta_file_.write(reinterpret_cast<const char*>(&page_count_), sizeof(page_count_));
        if (meta_file_.fail()) {
            LOG_ERROR("Failed to write page_count to metadata");
            meta_file_.close();  // 确保关闭文件
            return false;
        }

        meta_file_.write(reinterpret_cast<const char*>(&free_list_head_), sizeof(free_list_head_));
        if (meta_file_.fail()) {
            LOG_ERROR("Failed to write free_list_head to metadata");
            meta_file_.close();  // 确保关闭文件
            return false;
        }
        
        LOG_INFO("Saved metadata: next_page_id=" + std::to_string(next_page_id_) +
                 ", page_count=" + std::to_string(page_count_) +", free_list_head=" 
                 + std::to_string(free_list_head_));
        meta_file_.close();
        if (meta_file_.fail()) {
            LOG_ERROR("Failed to close metadata file properly");
            return false;
        }
        return true;
        
    } catch (const std::exception& e) {
        LOG_ERROR("Exception during metadata save: " + std::string(e.what()));
        return false;
    }
}

// 扩展文件
bool DiskManager::extend_file(size_t new_size) {
    try {
        // 定位到文件末尾
        db_file_.seekp(0, std::ios::end);
        
        // 计算需要扩展的大小
        size_t current_pos = db_file_.tellp();  
        if (new_size <= current_pos) {
            return true; // 不需要扩展
        }
        
        size_t bytes_to_add = new_size - current_pos;
        
        // 写入空数据来扩展文件
        char empty_data[1024] = {0};
        while (bytes_to_add > 0) {
            size_t chunk_size = (bytes_to_add > sizeof(empty_data)) ? sizeof(empty_data) : bytes_to_add;
            db_file_.write(empty_data, chunk_size);
            if (!db_file_) {
                LOG_ERROR("File extension failed at position: " + std::to_string(db_file_.tellp()));
                return false;
            }
            bytes_to_add -= chunk_size;
        }
        
        // 更新文件大小
        file_size_ = new_size;
        
        return true;
        
    } catch (const std::exception& e) {
        LOG_ERROR("Exception during file extension: " + std::string(e.what()));
        return false;
    }
}

// 验证页ID
bool DiskManager::validate_page_id(page_id_t page_id) const {
    return page_id >= 0 && page_id < next_page_id_;
}